From: Rui Matos Date: Thu, 14 Jun 2012 17:43:15 +0000 (+0200) Subject: boxpointer: Flip side if we would end outside the monitor X-Git-Tag: archive/raspbian/50.5-1+rpi1~1^2~1013^2^2~6368 X-Git-Url: https://dgit.raspbian.org/%22http://www.example.com/cgi/%22/%22http:/www.example.com/cgi/%22?a=commitdiff_plain;h=8d017ceaf1dffd3c35c15fea3dba810c6e36744a;p=gnome-shell.git boxpointer: Flip side if we would end outside the monitor This flips the BoxPointer if it ends outside the monitor and we have enough space to fit it inside, on the opposite side of the source actor. https://bugzilla.gnome.org/show_bug.cgi?id=678164 --- diff --git a/js/ui/boxpointer.js b/js/ui/boxpointer.js index 05356516c..d09c8bf77 100644 --- a/js/ui/boxpointer.js +++ b/js/ui/boxpointer.js @@ -18,7 +18,10 @@ const POPUP_ANIMATION_TIME = 0.15; * * An actor which displays a triangle "arrow" pointing to a given * side. The .bin property is a container in which content can be - * placed. The arrow position may be controlled via setArrowOrigin(). + * placed. The arrow position may be controlled via + * setArrowOrigin(). The arrow side might be temporarily flipped + * depending on the box size and source position to keep the box + * totally inside the monitor if possible. * */ const BoxPointer = new Lang.Class({ @@ -26,6 +29,7 @@ const BoxPointer = new Lang.Class({ _init: function(arrowSide, binProperties) { this._arrowSide = arrowSide; + this._userArrowSide = arrowSide; this._arrowOrigin = 0; this.actor = new St.Bin({ x_fill: true, y_fill: true }); @@ -199,8 +203,27 @@ const BoxPointer = new Lang.Class({ } this.bin.allocate(childBox, flags); - if (this._sourceActor && this._sourceActor.mapped) + if (this._sourceActor && this._sourceActor.mapped) { this._reposition(this._sourceActor, this._arrowAlignment); + + if (this._shouldFlip()) { + switch (this._arrowSide) { + case St.Side.TOP: + this._arrowSide = St.Side.BOTTOM; + break; + case St.Side.BOTTOM: + this._arrowSide = St.Side.TOP; + break; + case St.Side.LEFT: + this._arrowSide = St.Side.RIGHT; + break; + case St.Side.RIGHT: + this._arrowSide = St.Side.LEFT; + break; + } + this._reposition(this._sourceActor, this._arrowAlignment); + } + } }, _drawBorder: function(area) { @@ -327,6 +350,8 @@ const BoxPointer = new Lang.Class({ }, setPosition: function(sourceActor, alignment) { + this._arrowSide = this._userArrowSide; + // We need to show it now to force an allocation, // so that we can query the correct size. this.actor.show(); @@ -343,11 +368,7 @@ const BoxPointer = new Lang.Class({ if (!this._sourceActor) return; - // We need to show it now to force an allocation, - // so that we can query the correct size. - this.actor.show(); - - this._reposition(this._sourceActor, this._arrowAlignment); + this.setPosition(this._sourceActor, this._arrowAlignment); }, _reposition: function(sourceActor, alignment) { @@ -446,6 +467,39 @@ const BoxPointer = new Lang.Class({ -(this._yPosition + this._yOffset)); }, + _shouldFlip: function() { + let sourceAllocation = Shell.util_get_transformed_allocation(this._sourceActor); + let boxAllocation = Shell.util_get_transformed_allocation(this.actor); + let boxWidth = boxAllocation.x2 - boxAllocation.x1; + let boxHeight = boxAllocation.y2 - boxAllocation.y1; + let monitor = Main.layoutManager.findMonitorForActor(this.actor); + + switch (this._arrowSide) { + case St.Side.TOP: + if (boxAllocation.y2 > monitor.y + monitor.height && + boxHeight < sourceAllocation.y1 - monitor.y) + return true; + break; + case St.Side.BOTTOM: + if (boxAllocation.y1 < monitor.y && + boxHeight < monitor.y + monitor.height - sourceAllocation.y2) + return true; + break; + case St.Side.LEFT: + if (boxAllocation.x2 > monitor.x + monitor.width && + boxWidth < sourceAllocation.x1 - monitor.x) + return true; + break; + case St.Side.RIGHT: + if (boxAllocation.x1 < monitor.x && + boxWidth < monitor.x + monitor.width - sourceAllocation.x2) + return true; + break; + } + + return false; + }, + set xOffset(offset) { this._xOffset = offset; this._shiftActor();